# -*- coding: utf-8; py-indent-offset:4 -*-
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import datetime  # For datetime objects
import os.path  # To manage paths
import sys  # To find out the script name (in argv[0])
import pandas as pd

import backtrader as bt
import backtrader.indicators as btind

# Create a Stratey
class sma_cross(bt.Strategy):
    params = (
        ('sma_window', 25),
    )
    def log(self, txt, dt=None):
        ''' Logging function fot this strategy'''
        dt = dt or self.datas[0].datetime.datetime(0)
        print('%s, %s' % (dt.isoformat(), txt))

    def __init__(self):
        # Keep a reference to the "close" line in the data[0] dataseries
        self.dataclose = self.datas[0].close
        sma = btind.MovAv.SMA(self.data, period=self.params.sma_window)
        self.signal = btind.CrossOver(self.data.close, sma)
        # To keep track of pending orders

        self.order = None

    def notify(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return

        # Check if an order has been completed
        # Attention: broker could reject order if not enougth cash
        if order.status in [order.Completed, order.Canceled, order.Margin]:
            if order.isbuy():
                # self.log('BUY EXECUTED, %.2f' % order.executed.price)
                pass
            elif order.issell():
                pass
                # self.log('SELL EXECUTED, %.2f' % order.executed.price)

            self.bar_executed = len(self)

        # Write down: no pending order
        self.order = None

    def next(self):
        print(self.position.__bool__())
        # Simply log the closing price of the series from the reference
        # self.log('Close, %.2f' % self.dataclose[0])

        # Check if an order is pending ... if yes, we cannot send a 2nd one
        if self.order:
            return

        # Check if we are in the market
        if not self.position:

            # Not yet ... we MIGHT BUY if ...
            if self.signal > 0.0:
                    # BUY, BUY, BUY!!! (with default parameters)
                    # self.log('BUY CREATE, %.2f' % self.dataclose[0])
                    # Keep track of the created order to avoid a 2nd order
                    self.order = self.buy()
                    self.order = self.sell(exectype=bt.Order.StopTrail, trailpercent=0.08)
            # if self.signal < 0.0:
            #         # BUY, BUY, BUY!!! (with default parameters)
            #         # self.log('SELL CREATE, %.2f' % self.dataclose[0])
            #         # Keep track of the created order to avoid a 2nd order
            #         self.order = self.sell()


    def stop(self):
        self.log('(MA Period %2d) Ending Value %.2f' %
                 (self.params.sma_window, self.broker.getvalue()))

if __name__ == '__main__':
    # general run strategy
    cerebro = bt.Cerebro()
    cerebro.addwriter(bt.WriterFile, csv=True, out='../backtesting_csv_result/rev.csv')

    cerebro.addobserver(bt.observers.DrawDown)
    cerebro.addobserver(bt.observers.Benchmark)
    cerebro.addobserver(bt.observers.Trades)
    cerebro.addobserver(bt.observers.TimeReturn)
    cerebro.addobserver(bt.observers.DataTrades)

    cerebro.addstrategy(sma_cross)

    dataframe = pd.read_csv('../rbi.csv', index_col=0, parse_dates=True)
    dataframe['openinterest'] = 0
    data = bt.feeds.PandasData(dataname=dataframe)
    # Add the Data Feed to Cerebro
    cerebro.adddata(data)

    # Set our desired cash start
    cerebro.broker.setcash(100000.0)
    cerebro.broker.setcommission(commission=4,
                                 mult=10,
                                 margin=0.1)
    # Print out the starting conditions
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    # Run over everything
    cerebro.run()

    # Print out the final result
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    # Plot the result

    cerebro.plot()


    # optimization for the strategy

    # cerebro = bt.Cerebro()
    # cerebro.optstrategy(
    #     sma_cross,
    #     sma_window=range(5, 80))
    # dataframe = pd.read_csv('rbi.csv', index_col=0, parse_dates=True)
    # dataframe['openinterest'] = 0
    # data = bt.feeds.PandasData(dataname=dataframe
    #                            )
    # cerebro.adddata(data)
    # cerebro.broker.setcash(100000.0)
    # cerebro.broker.setcommission(commission=4,
    #                              mult=10,
    #                              margin=0.1)
    #
    # cerebro.run()



